package kr.ac.kaist.idb.csnql.clause;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Vector;

import kr.ac.kaist.idb.csnql.lib.Base64Coder;

public class SNQLQueryPacket implements Serializable{
	

	/**
	 * @brief Serial version UID which is automatically generated
	 */
	private static final long serialVersionUID = 1533220766341598013L;

	public long queryID;
	
	public ArrayList<Integer> targetRelatedCellInfo;
	
	ArrayList<String> queryPath;
	
	String targetRegionCoordinate;
	
	String query;
	
	String queryExecutionStartTime;
	
	/**
	 * @brief SELECT Item list
	 */
    public Vector<Object> select_;
    /**
     * @brief FROM Item list
     */
    public SNQLFromItem from_;
    /**
     * @brief WHERE clause
     */
    public SNQLExp where_;
    
    
    public SNQLQueryPacket()
    {
    	queryID = 0;
    	select_ = new Vector<Object>();
    	from_ = new SNQLFromItem();
    	queryPath = new ArrayList<String>();
    	targetRelatedCellInfo = new ArrayList<Integer>();
    	targetRegionCoordinate = new String();
    	query = new String();
    	queryExecutionStartTime = new String();
        where_ = new SNQLExpression();
    }


	public long getQueryID() {
		return queryID;
	}


	public void setQueryID(long queryID) {
		this.queryID = queryID;
	}


	public ArrayList<Integer> getTargetRelatedCellInfo() {
		return targetRelatedCellInfo;
	}


	public void setTargetRelatedCellInfo(ArrayList<Integer> targetRelatedCellInfo) {
		this.targetRelatedCellInfo = targetRelatedCellInfo;
	}


	public ArrayList<String> getQueryPath() {
		return queryPath;
	}


	public void setQueryPath(ArrayList<String> queryPath) {
		this.queryPath = queryPath;
	}


	public String getTargetRegionCoordinate() {
		return targetRegionCoordinate;
	}


	public void setTargetRegionCoordinate(String targetRegionCoordinate) {
		this.targetRegionCoordinate = targetRegionCoordinate;
	}


	public String getQuery() {
		return query;
	}


	public void setQuery(String query) {
		this.query = query;
	}


	public String getQueryExecutionStartTime() {
		return queryExecutionStartTime;
	}


	public void setQueryExecutionStartTime(String queryExecutionStartTime) {
		this.queryExecutionStartTime = queryExecutionStartTime;
	}


	public Vector<Object> getSelect_() {
		return select_;
	}


	public void setSelect_(Vector<Object> select_) {
		this.select_ = select_;
	}


	public SNQLFromItem getFrom_() {
		return from_;
	}


	public void setFrom_(SNQLFromItem from_) {
		this.from_ = from_;
	}


	public SNQLExp getWhere_() {
		return where_;
	}


	public void setWhere_(SNQLExp where_) {
		this.where_ = where_;
	}
	
	public String toString()
    {
		StringBuffer stringbuffer = new StringBuffer();
		
        stringbuffer.append("SELECT ");
        if(select_ != null && select_.size() != 0)
        	stringbuffer.append(select_.elementAt(0).toString());
        for(int i = 1; i < select_.size(); i++)
            stringbuffer.append(", " + select_.elementAt(i).toString());

        if(from_ != null)
            stringbuffer.append(" FROM " + from_.toString());

        if(where_ != null)
            stringbuffer.append(" WHERE " + where_.toString());

        return stringbuffer.toString();
    }
	
	/**
	 * @brief Marshalls the Event into a string and encodes it using Base64 coding
	 * @return A string that is Base64 encoded containing the marshalled event
	 * @throws IOException
	 */
	public String marshall() throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream out = new ObjectOutputStream(baos);
		out.writeObject(this);
		out.close();
		byte[] marshalledEvent = baos.toByteArray();
		String base64EndocdedMarshalledEvent = Base64Coder.encodeLines(marshalledEvent);
		return(base64EndocdedMarshalledEvent);
	}
	
	/**
	 * @brief Decodes the string from Base64 coding and unmarshalls the event and returns it
	 * @param base64EncodedMarshalledEvent A String that is encoded using Base64 coding and contains
	 *        a marshalled event
	 * @return The event object that was marshalled and encoded in the argument string 
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static SNQLQueryPacket unmarshall(String base64EncodedMarshalledEvent)
	throws IOException, ClassNotFoundException {
		byte[] marshalledEvent = Base64Coder.decodeLines(base64EncodedMarshalledEvent);
		ObjectInputStream ois =
			new ObjectInputStream(new ByteArrayInputStream(marshalledEvent));
		SNQLQueryPacket o = (SNQLQueryPacket)ois.readObject();
		ois.close();
		return(o);
	}

}
